package iot;

import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import iot.jtt808.DataPack;
import iot.jtt808.DataPackParser;
import netty.session.NettySession;
import netty.session.SessionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created by dave on 18-7-15 下午1:48.
 */
public class JTT808Handler extends ChannelInboundHandlerAdapter {
    private static final Logger L = LoggerFactory.getLogger(JTT808Handler.class);
    private SessionManager sessionManager;
    private MessageProcessor messageProcessor;
    private NettySession session;

    public JTT808Handler(SessionManager sm, MessageProcessor mp) {
        this.sessionManager = sm;
        this.messageProcessor = mp;
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        L.debug("设备建立Socket连接:" + channel.remoteAddress());
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        closeChannel(ctx);
        L.debug("设备Socket断连：" + ctx.channel().remoteAddress());
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg.getClass().isArray() && msg.getClass().getComponentType() == byte.class) {
            // byte[] bs = (byte[]) msg;
            // ctx.channel().writeAndFlush(Unpooled.wrappedBuffer(bs));
            DataPack dp = DataPackParser.parse((byte[]) msg);
            if (session == null) {
                session = sessionManager.addSession(dp.getSim(), ctx.channel());
            }
            messageProcessor.process(session, dp);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        closeChannel(ctx);
        L.debug("出现异常：" + ctx.channel().remoteAddress(), cause);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent && ((IdleStateEvent) evt).state() == IdleState.READER_IDLE) {
            closeChannel(ctx);
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }

    private void closeChannel(ChannelHandlerContext ctx) {
        ctx.close();
        if (session != null) {
            sessionManager.removeSession(session.getSessionId());
        }
    }
}
